import configparser
import os
import random
import time

import pygame
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait

# 全局变量
isFirst = True


class Question:
    # 定义一个Question类
    def __init__(self, no, title):
        # 初始化Question类的属性
        self.no = no
        # 问题的编号
        self.title = title


'''
    获取用户所有未提交正确的代码
'''


def set_questions(problems, questions):
    # 遍历problems列表中的每个问题
    for problem in problems:
        # 将问题文本按换行符分割
        test = problem.text.split('\n')
        # 获取问题状态
        status = test[0]
        # 获取问题编号
        no = test[1]
        # 如果问题状态不为Y
        if status != "Y":
            # 如果问题状态为N
            if status == "N":
                # 打印问题编号和问题名称
                # print("题目编号：{}，题目名称：{}".format(no, test[2]))
                # 将问题添加到questions列表中
                questions.append(Question(no, test[2]))
            # 如果问题状态不为N
            else:
                # 打印问题状态和问题名称
                # print("题目编号：{}，题目名称：{}".format(status, test[2]))
                # 将问题添加到questions列表中
                questions.append(Question(status, test[1]))


'''
  自动提交正确代码
'''


def auto_submit_answer(question, driver, code, account):
    global isFirst
    # 随机生成提交时间
    random_time = random.randint(5, 10)
    print("正在提交题目编号：{}，题目名称：{}，预计提交时间：{}秒".format(question.no, question.title, time))
    WebDriverWait(driver, random_time)
    # 跳转到题目页面
    driver.find_element(By.PARTIAL_LINK_TEXT, '问题').click()
    print(question.no)
    if int(question.no) < 1050:
        driver.find_element(By.XPATH, '//*[@id="page"]/small/ul/li[2]/a').click()
    else:
        driver.find_element(By.XPATH, '//*[@id="page"]/small/ul/li[4]/a').click()
    # 进入问题
    driver.find_element(By.PARTIAL_LINK_TEXT, question.title).click()
    # 找到提交按钮
    driver.find_element(By.PARTIAL_LINK_TEXT, '提交').click()

    if isFirst:
        # 下拉选择java语言 //*[@id="language"]
        ele = driver.find_element(By.XPATH, '//*[@id="language"]')
        select_ele = Select(ele)
        select_ele.select_by_index(3)
        # 确认弹窗
        driver.switch_to.alert.accept()
        isFirst = False

    # 找到代码输入框 //*[@id="source"]/div[2]
    driver.execute_script("editor.setValue(`{}`)".format(code))
    time.sleep(5)
    # 提交代码
    driver.find_element(By.XPATH, '//*[@id="Submit"]').click()
    time.sleep(5)
    # WebDriverWait(driver, 10)
    # # 跳转页面到检测
    driver.execute_script(f"window.location.href='http://59.73.87.13/status.php?user_id={account}'")
    WebDriverWait(driver, 20)
    # # 回到问题页面
    driver.find_element(By.XPATH, '//*[@id="navbar"]/ul[1]/li[2]/a').click()
    WebDriverWait(driver, 5)


def init_files(path):
    files = os.listdir(path)
    print(f'文件加载成功，共{len(files)}个')
    return files


def match_the_answer(no, files):
    # 定义一个空字典f，用于存储匹配到的文件名
    f = {}
    # 定义一个空字符串code，用于存储读取到的代码
    code = ''
    # 遍历files列表
    for file in files:
        # 如果文件名以no开头
        if file.startswith(no):
            # 读取数据
            f = file
            # 跳出循环
            break
    # 打开code文件夹下的f文件，以只读方式打开，编码格式为utf-8
    try:
        with open("code/" + f, "r", encoding='utf-8') as file:
            # 遍历文件中的每一行
            for line in file:
                # 将换行符替换为\n
                line = line.replace('\n', '\\n')
                # 将每一行添加到code字符串中
                code += line
        # 返回code字符串
        return code
    except:
        print("文件读取失败,自动跳过该题目")
        return None


def start():
    config = configparser.ConfigParser()
    config.read('config.properties')
    account = config.get('DEFAULT', 'account')
    password = config.get('DEFAULT', 'password')
    # end： 提交到哪个题目结束
    end = config.get('DEFAULT', 'end')
    # 创建一个Edge浏览器驱动
    driver = webdriver.Edge()
    # 浏览器页面最大化
    driver.maximize_window()

    # 默认打开obj登录页面
    driver.get("http://59.73.87.13/loginpage.php")
    # 找到账号输入框
    driver.find_element(By.XPATH, '//*[@id="login"]/div[1]/div/input').send_keys(account)
    # 找到密码输入框
    driver.find_element(By.XPATH, '//*[@id="login"]/div[2]/div/input').send_keys(password)
    time.sleep(5)

    driver.find_element(By.XPATH, '//*[@id="login"]/div[3]/div[1]/button').click()

    # 等待资源加载完成
    WebDriverWait(driver, 5)

    # 通过js跳转
    driver.execute_script("window.location.href='http://59.73.87.13/index.php'")

    # 点击问题
    driver.find_element(By.XPATH, '//*[@id="navbar"]/ul[1]/li[2]/a').click()
    WebDriverWait(driver, 5)

    # 取出所有的题（第一页）强制默认指定第一页
    driver.find_element(By.XPATH, '//*[@id="page"]/small/ul/li[2]/a').click()

    problems = driver.find_elements(By.XPATH, '//*[@id="problemset"]/tbody/tr')

    # 遍历所有单数题 将所有错误和未提交的信息保存到数组中
    questions = []
    set_questions(problems, questions)

    # 跳转到第二页
    driver.find_element(By.XPATH, '//*[@id="page"]/small/ul/li[4]/a').click()

    # 取出第二页的题
    problems = driver.find_elements(By.XPATH, '//*[@id="problemset"]/tbody/tr')
    set_questions(problems, questions)

    # 打印所有未提交的题目
    for q in questions:
        print("题目编号：{}，题目名称：{}".format(q.no, q.title))

    # 提示正在加载答案
    print("共{}道题未完成".format(len(questions)))
    print("加载正确答案中....")
    print("正确答案加载完成，开始提交")
    # 开始自动提交问题
    for q in questions:
        # 找到当前问题的答案
        code = match_the_answer(q.no, files)
        if code is None:
            continue
        # 如果到了指定的题提交后就停止运行
        if q.no == end:
            break
        # 自动提交问题
        auto_submit_answer(q, driver, code, account)
        print("题目编号：{}，题目名称：{} 已提交".format(q.no, q.title))
        # break
    # 关闭驱动，回收资源
    time.sleep(5)
    driver.quit()


if __name__ == '__main__':
    pygame.init()
    agree = input("本人原承担一切后果并且已开启了vpn或者是在校内机房（y/n）： ")
    if agree == 'y' or agree == 'Y':
        print('开始刷题')
    else:
        print('取消刷题')
        exit(0)
    files = init_files("code")
    start()
    print('刷题结束了喵~~~0')
